package com.ly.mpayment.persist.service.downshopproduct;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.stream.Collectors;

import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.ly.mpayment.core.util.*;
import com.ly.mpayment.persist.entity.*;
import com.ly.mpayment.persist.service.downrechargeflow.IDownRechargeFlowService;
import com.ly.mpayment.persist.service.user.IUserService;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ly.mpayment.persist.hibernate.Page;
import com.ly.mpayment.persist.service.AbstractService;
import com.ly.mpayment.persist.service.downproductlog.IDownProLogService;
import com.ly.mpayment.persist.service.matchingstrategy.IMatchingStrategyService;

@Service
public class DownShopProductServiceImpl extends AbstractService<DownShopProduct, Serializable> implements IDownShopProductService{

	@Autowired
	IDownProLogService logService;

	@Autowired
	IMatchingStrategyService matchingService;

	@Autowired
	IDownRechargeFlowService rechargeFlowService;


	@Override
	public boolean addDownshopproduct(DownShopProduct product,User userAdmin) {
		if(product != null){
			product.setDownprouuid(code(product));
			this.saveOrUpdate(product);
			DownProductLog log = null;
			log = new DownProductLog();
			log.setOperationtarget(Config.product[0]);
			log.setDownShopProduct(product);
			if(userAdmin != null){
				log.setUserLog(userAdmin);
			}
			logService.addDownprolog(log);
			return true;
		}
		return false;
	}

	/**
	 * 生成产品编码 运营商 省份 公司名称 面值
	 * @param product
	 * @return
	 */
	private String code(DownShopProduct product){
		String code = product.getOperators().getCode()+"_"+product.getProvincialInformation().getProvincecode()+"_"+product.getBusinessType().getBusCode()+"_"+product.getUser().getPhonenum()+"_"+product.getDownfacevalue();
		return code;
	}

	@Override
	public boolean updateDownshopproduct(DownShopProduct product,User userAdmin,boolean enable) {
		if(product != null){
			this.saveOrUpdate(product);
			DownProductLog log = null;
			log = new DownProductLog();
			log.setOperationtarget(Config.product[1]);
			log.setDownShopProduct(product);
			if(enable){
				log.setRemark("修改产品状态:"+ (product.getStatus() == 1 ?"启用" : "禁用"));
			}else{
				log.setRemark(product.getDiscount().toString());
			}
			if(userAdmin != null){
				log.setUserLog(userAdmin);
			}
			logService.addDownprolog(log);
			return true;
		}
		return false;
	}

	@Override
	public DownShopProduct findById(String id) {
		return this.findUnique("select d from DownShopProduct d left join fetch d.businessType left join fetch d.operators left join fetch d.provincialInformation left join fetch d.user where d.downprouuid =?", id);
	}


	@Override
	public DownShopProduct findByNotUseUUId(String id,String userId) {
		if(CookieRedis.get("downProductCheck").equals("true")){
			return this.findUnique("select d from DownShopProduct d left join fetch d.businessType left join fetch d.operators left join fetch d.provincialInformation left join fetch d.user where ( d.status = 1 or d.status = 2)  and d.downprouuid =? and d.user.useruuid = ? ", id,userId);
		}
		return this.findUnique("select d from DownShopProduct d left join fetch d.businessType left join fetch d.operators left join fetch d.provincialInformation left join fetch d.user where  d.status = 1  and d.downprouuid =?  and d.user.useruuid = ? ", id,userId);
	}


	@Override
	public Page<DownShopProduct> findPageDownshopproduct(Map<String, Object> parameters, int start, int pageSize) {
		return this.findPageByNamed(getPageSql(parameters), parameters, start, pageSize);
	}

	private String getPageSql(Map<String, Object> parameters){
		String sql = "select d from DownShopProduct d left join fetch d.businessType left join fetch d.operators left join fetch d.provincialInformation left join fetch d.user  "
				+ " where d.status != 0  #[ and d.operators.operatoruid = :operatoruid]# #[ and d.provincialInformation.provinceuuid = :provinceuuid]# #[and d.status = :status ]#"
				+ " #[ and d.businessType.busuuid = :busuuid]#  #[ and d.price = :price]# "
				+ " #[ and d.fastchargetype = :fastchargetype]# #[ and d.validity = :validity]#  #[ and d.cityName = :cityName]#  #[ and d.auto = :auto]# " +
				"   #[ and d.discount = :discount]# ";

		if(parameters.containsKey(":useruuid")){
			JSONArray array = JSONArray.fromObject(parameters.get(":useruuid"));
			List<String> list = new ArrayList<>();
			for(int i = 0 ; i < array.size();i++){
				list.add("'"+array.getString(i)+"'");
			}
			if(!list.isEmpty()){
				sql += " and d.user.useruuid in("+ org.apache.commons.lang.StringUtils.join(list.toArray(),",")+ ") ";
			}
			parameters.remove(":useruuid");
		}
		if(parameters.containsKey(":downfacevalue")){
			 //#[ and d.downfacevalue = :downfacevalue]#
			JSONArray array = JSONArray.fromObject(parameters.get(":downfacevalue"));
			List<String> list = new ArrayList<>();
			for(int i = 0 ; i < array.size();i++){
				list.add("'"+array.getString(i)+"'");
			}

			sql += " and d.downfacevalue  in("+ org.apache.commons.lang.StringUtils.join(list.toArray(),",")+ ") ";
			parameters.remove(":downfacevalue");
		}

		sql += "  order by d.user.useruuid,d.downprouuid " ;
		return sql;
	}

	/**
	 * 查询下游渠道商是否包含对应的产品
	 */
	@Override
	public List findProductBus(String operators,String province,String busCode,String useruuid,BigDecimal faceValue) {
		StringBuffer sb = new StringBuffer();
		sb.append(" select d.downprouuid from downshopproduct d , operators o ,provincialinformation p , ");
		sb.append(" businesstype b where d.status = 1 and d.operatoruid = o.operatoruid and   p.provinceuuid = d.provinceuuid and ");
		sb.append(" b.busuuid = d.busuuid and o.operatoruid ='");
		sb.append(operators);
		sb.append("' and (p.provincename = '");
		sb.append(province);
		sb.append("' or p.provinceuuid='");
		sb.append(CookieRedis.get("globalCountry"));
		sb.append("' ) and b.buscode ='");
		sb.append(busCode);
		sb.append("' ");
		sb.append(" and d.useruuid ='");
		sb.append(useruuid);
		sb.append("' and d.price * d.discount <=");
		sb.append(faceValue);
		sb.append(" order by d.price * d.discount limit 1");
		return this.getSession().createSQLQuery(sb.toString()).list();
	}

//	@Override
//	public DownShopProduct findByUUId(String id) {
//		return this.findUnique("select d from DownShopProduct d where d.status != 0 and d.downprouuid = ? ", id);
//	}

	@Override
	public DownShopProduct findByIdAndProductCode(String useruuid, String productCode) {
		return this.findUnique("select d from DownShopProduct d where  d.user.useruuid = ? and d.productCode = ?", useruuid,productCode);
	}

	@Override
	public List<DownShopProduct> getProductList(String useruuid) {
		return this.find("select d from DownShopProduct d left join fetch d.provincialInformation left join fetch d.operators left join fetch d.businessType where (d.status = 1 or d.status = 2)  and d.user.useruuid = ?",useruuid);
	}

	@Override
	public boolean updateDownshopProductAuto(DownShopProduct product, User userAdmin) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public DownShopProduct findProductStrategy(String id) {
		return this.findUnique("select d from DownShopProduct d left join fetch d.businessType left join fetch d.operators left join fetch d.provincialInformation left join fetch d.user where d.status = 1 and d.downprouuid =?", id);
	}

	@Override
	public List<DownShopProduct> exportDownCount(Map<String, Object> parameters) {
		return this.findByNamed(getPageSql(parameters), parameters);
	}

	@Override
	public DownShopProduct searchBatchProduct(String operatoruid, String provinceuuid, String busuuid, String useruuid,
			String faceValue, BigDecimal price,String productCode) {
		return this.findUnique(" select d from DownShopProduct d left join fetch d.businessType bs left join fetch d.operators op left join fetch d.provincialInformation pr left join fetch d.user where op.operatoruid = ? and pr.provinceuuid = ? and bs.busuuid = ?"
				+ " and d.user.useruuid = ? and d.downfacevalue = ? and d.price = ? and d.productCode = ? ", operatoruid,provinceuuid,busuuid,useruuid,faceValue,price,productCode);//
	}

	@Override
	public List<DownShopProduct> findBatchEditUpProduct(String provinceuuid, String operatoruid, String busuuid,String useruuid,String cityName,String discount,String downfacevalue) {
		String sql = "select d from DownShopProduct d left join fetch d.businessType bs left join fetch d.operators op left join"
				+ " fetch d.provincialInformation pr left join fetch d.user where op.operatoruid = ? and pr.provinceuuid = ? "
				+ " and bs.busuuid = ?  and d.status = 1 " +
				(StringUtils.isBlank(useruuid) ? "" : " and d.user.useruuid in ("+useruuid+")") +
				(StringUtils.isBlank(cityName) ? "" : " and d.cityName = '"+cityName+"'") +
				(StringUtils.isBlank(downfacevalue) ? "" : " and d.downfacevalue in("+downfacevalue+")") +
				(StringUtils.isBlank(discount) ? "" : " and d.discount = "+discount+"");
		return this.find(sql,operatoruid, provinceuuid,busuuid);
	}

	/**
	 * 设置产品为自动
	 */
	@Override
	public boolean updateDownshopProduct(User user,DownShopProduct product) {
		if(user != null){
			//删除匹配数据
			MatchingStrategy match = this.matchingService.findByDownUuid(user.getUseruuid(),product.getProvincialInformation().getProvinceuuid(),
					product.getOperators().getOperatoruid(),product.getBusinessType().getBusuuid());
			if(match != null){
				matchingService.deleteStrategy(match);
			}
			this.updateEntity(product);
			return true;
		}
		return false;
	}

	@Override
	public void updateProduct(DownShopProduct downShopProduct) {
		if(downShopProduct != null){
			this.updateEntity(downShopProduct);
		}
	}

	@Override
	public DownShopProduct findByIdAndFacevalue(String useruuid, String faceValue) {
		return this.findUnique("select d from DownShopProduct d left join fetch d.businessType  left join fetch d.operators  left join fetch d.provincialInformation  where d.status = 1 and d.user.useruuid = ? and d.downfacevalue = ?", useruuid,faceValue);
	}

	@Override
	public List<DownShopProduct> findByUuidDown(String useruuid) {
		return this.find("select d from DownShopProduct d where  d.user.useruuid = ? "
				, useruuid);
	}

	@Override
	public List<DownShopProduct> findByUuidDownProduct(String useruuid,String provinceuuid, String operatoruid,String busuuid) {
		return this.find("select d from DownShopProduct d left join fetch d.businessType b left join fetch d.operators o " +
				" left join fetch d.provincialInformation p where  d.user.useruuid = ? and b.busuuid = ? and o.operatoruid = ? and p.provinceuuid = ?"
				, useruuid,busuuid,operatoruid,provinceuuid);
	}

	@Override
	public List<DownShopProduct> findByGlobalCountry(String uid,String money,String busCode,String operatoruid) {
		String sql = " select d from DownShopProduct d left join fetch d.businessType b left join fetch d.operators  left join fetch d.provincialInformation p  where " +
				" d.status = 1 and d.user.useruuid = ? and d.downfacevalue = ? and d.provincialInformation.provinceuuid = ? and b.busCode =? " +
				" and d.operators.operatoruid =? order by d.discount ";
		return this.find(sql,uid,money,CookieRedis.get("globalCountry"),busCode,operatoruid);
	}

	@Override
	public List<DownShopProduct> findByUuidAndProvice(String uid, String money, String province, String busCode,String operatoruid) {
		return this.find("select d from DownShopProduct d left join fetch d.businessType b left join fetch d.operators  left join fetch d.provincialInformation p  where " +
				"d.status = 1 and d.user.useruuid = ? and d.downfacevalue = ? and b.busCode =? and d.operators.operatoruid =? order by d.discount", uid,money,busCode,operatoruid);
		//and p.provincename = ?
	}

	@Override
	public List<DownShopProduct> findByUuidAndCity(String uid, String province, String city, String money, String busCode,String operatoruid) {
		String sql = String.format(" select d from DownShopProduct d left join fetch d.businessType b left join fetch d.operators  left join fetch d.provincialInformation p " +
				" where d.status = 1 and d.user.useruuid = ? and d.downfacevalue = ?  and b.busCode =?  " +
				//and  d.cityName = ? and p.provincename =?
				" and d.provincialInformation.provinceuuid = ? and d.operators.operatoruid =? order by d.discount ");

		return this.find(sql, uid,money,busCode,CookieRedis.get("globalCountry"),operatoruid);
	}

	@Override
	public DownShopProduct findByYiSai(String productid, String partnerid) {
		if(CookieRedis.get("downProductCheck").equals("true")){
			return this.findUnique("select d from DownShopProduct d left join fetch d.businessType left join fetch d.operators left join fetch d.provincialInformation left join fetch d.user where ( d.status = 1 or d.status = 2)  and d.remark like ? and d.user.useruuid = ? ", "%"+productid+"%",partnerid);
		}
		return this.findUnique("select d from DownShopProduct d left join fetch d.businessType left join fetch d.operators left join fetch d.provincialInformation left join fetch d.user where  d.status = 1  and d.remark like ?  and d.user.useruuid = ? ", "%"+productid+"%",partnerid);
	}

	@Autowired
	IUserService userService;

	@Override
	public String handleBatchStatus(String data,String token) {
		JSONObject json = JsonUtils.converToJson(data);
		JSONArray products = json.getJSONArray("products");
		if (token != null) {
			DecodedJWT jwt;
			jwt = JWT.decode(token);
			if (jwt != null) {
				JSONObject jsonUser = JsonUtils.converToJson(jwt.getSubject());
				if (json != null) {
					User userAdmin = userService.findByUserid(jsonUser.getString(Config.tokenSignAttr));
					if (UserUtil.checkRole(userAdmin)) {
						for(int i = 0 ; i < products.size(); i++){
							DownShopProduct product = findById(products.getJSONObject(i).getString("downprouuid"));
							if(product != null){
								product.setStatus(json.getInt("status"));
								updateProduct(product);
							}
						}
						return ResultMessage.getSucceed(null);
					}
				}
			}
		}
		return ResultMessage.getFailt("");
	}

	@Override
	public BigInteger findProductStrategyCount(String upprouuids) {
		return (BigInteger) this.getSession().createSQLQuery(" select count(*) from downshopproduct d " +
				" inner join businesstype b on b.busuuid = d.busuuid" +
				" inner join operators o on o.operatoruid = d.operatoruid " +
				" inner join provincialinformation p on p.provinceuuid = d.provinceuuid " +
				" inner join user u on u.useruuid = d.useruuid " +
				" where d.status = 1 and d.downprouuid in  ("+upprouuids+")").uniqueResult();
	}


	@Override
	public void updateProductPrice(ProductPrice price) {
		DownShopProduct product = this.findById(price.getProductId().getDownprouuid());
		product.setDiscount(price.getAfterDiscount());
		product.setDiscountAmount(product.getPrice().multiply(price.getAfterDiscount()));
		logger.info("updateProductPrice:"+product.getDownprouuid()+","+price.getAfterDiscount()+","+product.getDiscountAmount());
		this.updateProduct(product);
	}
	/**
	 * 删除产品 检查产品是否使用过
	 *
	 * @param data
	 * @return
	 */
	@Override
	public String deleteDownProduct(String data) {
		JSONArray array = JSONArray.fromObject(data);
		for(int i = 0 ; i < array.size() ; i++){
			DownShopProduct product = this.findById(array.getJSONObject(i).getString("downprouuid"));
			if(product == null){
				return ResultMessage.getFailt("产品不存在");
			}
			//检查产品是否存在匹配
			if(matchingService.findByDownCount(product.getDownprouuid())){
				return ResultMessage.getFailt("产品存在匹配,禁止删除");
			}
			//查询产品是否存在订单
			int count = this.rechargeFlowService.findbyProduct(product.getDownprouuid());
			if(count > 0){
				return ResultMessage.getFailt("产品被使用,禁止删除");
			}
			logService.deleteLog(product);
			this.getSession().createSQLQuery(" delete from downshopproduct where downprouuid = '"+product.getDownprouuid()+"'").executeUpdate();
		}
		return ResultMessage.getSucceed();
	}
}
